package com.ls.fw.web.file.controller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import com.ls.fw.commons.core.bean.ResultObj;
import com.ls.fw.commons.core.utils.io.FileUtils;
import com.ls.fw.mvc.springmvc.base.BaseController;
import com.ls.fw.mvc.springmvc.util.ViewUtil;
import com.ls.fw.web.core.servlet.utils.HttpUtils;
import com.ls.fw.web.file.bean.DownInfo;
import com.ls.fw.web.file.bean.FileErrorInfo;
import com.ls.fw.web.file.bean.UploadFileInfo;

/**
 * 
 * 
 * @author lisheng
 * @date 2015年6月27日 下午3:59:42
 * @version V1.0
 */
public abstract class BaseFileController extends BaseController{
    
    /**
     * 下载文件
     * 
     * @author lisheng
     * @date 2015年9月9日 下午10:28:36
     * @version V1.0
     * @param request
     * @param name
     * @param relativeFilePath
     * @return
     * @throws IOException
     */
    public ResponseEntity<byte[]> download(HttpServletRequest request,
			String name, String relativeFilePath) throws IOException {
		String ctxPath = request.getSession().getServletContext()
				.getRealPath("/")
				+"/"+ relativeFilePath;
		File file = new File(ctxPath);
		return this.download(request, name, file);
	}

    
    /**
     * 下载文件
     * 
     * @author lisheng
     * @date 2015年9月9日 下午10:28:47
     * @version V1.0
     * @param request
     * @param name
     * @param file
     * @return
     * @throws IOException
     */
	public ResponseEntity<byte[]> download(HttpServletRequest request,
			String name, File file) throws IOException {
		return this.download(request, name, FileUtils.readFileToByteArray(file));
	}
	
	
	/**
	 * 下载文件
	 * 
	 * @author lisheng
	 * @date 2015年10月24日 下午5:11:18
	 * @version V1.0
	 * @param request
	 * @param name
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public ResponseEntity<byte[]> download(HttpServletRequest request,
			String name, InputStream is) throws IOException {
//		ByteArrayOutputStream os = new ByteArrayOutputStream();
//		IOUtils.copy(is, os);
//		//写入os操作
//		os.flush();
		return this.download(request, name, IOUtils.toByteArray(is));
	}
	
	/**
	 * 下载文件
	 * @author lisheng
	 * @date 2015年9月9日 下午10:31:25
	 * @version V1.0
	 * @param request
	 * @param name
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public ResponseEntity<byte[]> download(HttpServletRequest request,
			String name, byte[] file) throws IOException {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//		headers.setContentDispositionFormData("attachment",
//				HttpUtils.encode(request, name));
		String filename =  HttpUtils.encode(request,name);
		StringBuilder builder = new StringBuilder("name=\"");
	    builder.append("attachment").append('\"');
        if (StringUtils.isNotBlank(filename)) {
            builder.append("; filename=\"");
            builder.append(filename).append('\"');
        }
        headers.set(HttpHeaders.CONTENT_DISPOSITION, builder.toString());
		return new ResponseEntity<byte[]>(file,
				headers, HttpStatus.OK);
	}

	/**
	 * 下载文件
	 * 
	 * @param is
	 * @param response
	 * @return
	 * @throws IOException
	 * @author ls 2014年9月9日下午10:29:18
	 */
	protected int down(InputStream is, HttpServletResponse response)
			throws IOException {
		return FileCopyUtils.copy(is, response.getOutputStream());
	}
	
	
	/**
	 * 下载
	 * 
	 * @author lisheng
	 * @date 2015年9月10日 下午8:32:31
	 * @version V1.0
	 * @param request
	 * @return
	 * @throws IOException
	 */
	public ResponseEntity<byte[]> download(HttpServletRequest request) throws IOException {
		 return null;
	}
	
	
	/**
	 * 上传文件处理器
	 * 
	 * @author lisheng
	 * @date 2015年9月11日 下午7:17:36
	 * @version V1.0
	 * @param request
	 * @param handler
	 * @throws Exception
	 */
	public void uploadHandler(DefaultMultipartHttpServletRequest request, FileUploadHandler handler
			) throws Exception {
		//创建一个通用的多部分解析器
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getServletContext());
        //判断 request 是否有文件上传,即多部分请求
        if(multipartResolver.isMultipart(request)){
           Map<String,MultipartFile> map =  request.getFileMap();
            //取得request中的所有文件名
            Iterator<Entry<String, MultipartFile>> iter = map.entrySet().iterator();
            while(iter.hasNext()){
                //记录上传过程起始时的时间，用来计算上传时间
                int pre = (int) System.currentTimeMillis();
                Entry<String, MultipartFile> e = iter.next();
                //取得上传文件
                String name = e.getKey();
                MultipartFile file = e.getValue();
                if(file != null){
                    handler.save(name,file,request);
                }
                //记录上传该文件后的时间
                int finaltime = (int) System.currentTimeMillis();
                this.logger.debug("保存"+file.getOriginalFilename()+"耗时："+(finaltime - pre)/1000.0+"s");
            }
        }
    }

	protected ModelAndView doUpload(DefaultMultipartHttpServletRequest request, WebRequest webRequest
			, String viewName, UploadWorkHandler mapper) throws Exception{
		ResultObj obj = mapper.doWork(request,webRequest);
		return ViewUtil.convert(this.returnResult(obj, viewName), webRequest,obj.isForceJson());
	}


	protected ModelAndView doUpload(DefaultMultipartHttpServletRequest request, WebRequest webRequest
			, UploadWorkHandler mapper, UploadReturnResultHandler returnHandler) throws Exception{
		ResultObj obj = mapper.doWork(request,webRequest);
		if(returnHandler==null){
			return ViewUtil.convert(this.returnResult(obj,""), webRequest,obj.isForceJson());
		}
		return returnHandler.returnHandler(obj,request);
	}
	
    /**
     * 文件上传处理器
     * @author  sheng.li
     * @version  [版本号, 2015年9月11日]
     * @see  [相关类/方法]
     * @since  [产品/模块版本]
     */
    public interface FileUploadHandler{
    	
    	/**
    	 * @author lisheng
    	 * @date 2015年10月12日 下午8:27:05
    	 * @version V1.0
    	 * @param name 文件域名
    	 * @param file 文件
    	 * @param request
    	 * @return
    	 * @throws Exception
    	 */
        boolean save(String name, MultipartFile file, HttpServletRequest request
        		 ) throws Exception;
    }
    
	public interface UploadHandler {
		/**
		 * 文件是否有效
		 * @author lisheng
		 * @date 2015年10月16日 下午8:41:00
		 * @version V1.0
		 * @param name 文件域名称
		 * @param file 文件
		 * @param request
		 * @return
		 * @throws Exception
		 */
		boolean isValid(String name, MultipartFile file, HttpServletRequest request,UploadResultHandler resultHandler) throws Exception;
		
		public boolean save(String name, MultipartFile file,
				HttpServletRequest request,UploadResultHandler resultHandler) throws Exception;
	}
	
	
	/**
	 * 上传文件的返回值处理
	 * @author lisheng
	 * @date 2015年10月18日 下午8:17:05
	 * @version V1.0
	 */
	public interface UploadReturnResultHandler{
		ModelAndView returnHandler(ResultObj obj,HttpServletRequest request);
	}
	
	
	/**
	 * 下载结果处理器
	 * @author lisheng
	 * @date 2015年10月18日 下午9:43:42
	 * @version V1.0
	 */
	public interface DownReturnResultHandler{
		
		public Object noExists(DownInfo downInfo, HttpServletRequest request, Exception e);
		
		/**
		 * 参数非法
		 * 
		 * @author lisheng
		 * @date 2015年10月18日 下午9:43:15
		 * @version V1.0
		 * @param request
		 * @return
		 */
		public Object paraInValid(DownInfo downInfo, HttpServletRequest request, Exception e);
		
		/**
		 * 返回结果
		 * 
		 * @author lisheng
		 * @date 2015年10月18日 下午9:43:26
		 * @version V1.0
		 * @param file
		 * @param request
		 * @return
		 */
		public Object returnHandler(DownInfo downInfo, File file,HttpServletRequest request);
	}
	/**
	 * 上传文件的结果处理
	 * @author lisheng
	 * @date 2015年10月18日 下午8:16:45
	 * @version V1.0
	 */
	public interface UploadResultHandler{
		/**
		 * 上传成功
		 * @author lisheng
		 * @date 2015年10月16日 下午9:12:22
		 * @version V1.0
		 * @param name 文件域名称
		 * @param destfile
		 * @param fileInfo
		 * @throws Exception
		 */
		void success(String name, File destfile, UploadFileInfo fileInfo)throws Exception;
		
		
		/**
		 * 上传失败
		 * 
		 * @author lisheng
		 * @date 2015年10月16日 下午9:12:37
		 * @version V1.0
		 * @param name 文件域名称
		 * @param file
		 * @param info
		 * @param e
		 * @throws Exception
		 */
		void fail(String name, MultipartFile file, FileErrorInfo info ,Exception e)throws Exception;
	}
	
	/**
	 * 上传文件处理器
	 * 
	 * @author lisheng
	 * @date 2015年10月12日 下午8:39:41
	 * @version V1.0
	 */
	public interface UploadWorkHandler extends WorkHandler{
		
		ResultObj doWork(DefaultMultipartHttpServletRequest request, WebRequest webRequest) throws Exception;
	}
	
}





